/**
 * Axios HTTP 请求配置和拦截器
 * 
 * 功能特性：
 * 1. 无默认超时限制 - 允许长时间请求
 * 2. 可选的超时配置 - 支持按请求设置超时
 * 3. 请求取消功能 - 支持取消特定请求或所有请求
 * 4. 完善的错误处理 - 包括超时、网络错误、取消请求等
 * 5. 统一的响应格式处理
 * 
 * 使用示例：
 * 
 * // 基本使用（无超时）
 * const data = await httpService.get('/api/users');
 * 
 * // 设置超时（30秒）
 * const data = await httpService.get('/api/users', {}, 30000);
 * 
 * // 带请求ID（可取消）
 * const requestId = 'user-list-' + Date.now();
 * const data = await httpService.get('/api/users', {}, undefined, requestId);
 * 
 * // 取消特定请求
 * httpService.cancelRequest(requestId);
 * 
 * // 取消所有请求
 * httpService.cancelAllRequests();
 * 
 * // 设置默认超时
 * httpService.setDefaultTimeout(30000);
 * 
 * // 清除默认超时
 * httpService.clearDefaultTimeout();
 */

import axios from 'axios';
import type { InternalAxiosRequestConfig, AxiosResponse, AxiosError, CancelTokenSource } from 'axios';
import type { ApiResponse } from '../api/types';
import { ElMessage } from 'element-plus';

// 扩展配置类型以包含元数据
interface ExtendedAxiosRequestConfig extends InternalAxiosRequestConfig {
    metadata?: {
        startTime: Date;
    };
}

// 请求取消令牌管理器
class CancelTokenManager {
    private cancelTokens: Map<string, CancelTokenSource> = new Map();

    // 创建取消令牌
    createToken(requestId: string): CancelTokenSource {
        const token = axios.CancelToken.source();
        this.cancelTokens.set(requestId, token);
        return token;
    }

    // 取消特定请求
    cancelRequest(requestId: string): boolean {
        const token = this.cancelTokens.get(requestId);
        if (token) {
            token.cancel('请求被用户取消');
            this.cancelTokens.delete(requestId);
            return true;
        }
        return false;
    }

    // 取消所有请求
    cancelAllRequests(): void {
        this.cancelTokens.forEach((token, requestId) => {
            token.cancel('所有请求被取消');
        });
        this.cancelTokens.clear();
    }

    // 移除令牌（请求完成后）
    removeToken(requestId: string): void {
        this.cancelTokens.delete(requestId);
    }
}

// 创建取消令牌管理器实例
const cancelTokenManager = new CancelTokenManager();

// 创建axios实例
const instance = axios.create({
    baseURL: '/api',
    // 移除超时配置，允许长时间请求
    // timeout: 10000,
    headers: {
        'Content-Type': 'application/json',
    },
});

// 请求拦截器
instance.interceptors.request.use(
    (config: InternalAxiosRequestConfig) => {
        // 添加认证token（如果可用）
        const token = localStorage.getItem('token');
        if (token) {
            config.headers.Authorization = `Bearer ${token}`;
        }

        // 添加请求时间戳用于调试
        (config as ExtendedAxiosRequestConfig).metadata = { startTime: new Date() };

        // 详细的请求调试信息
        // console.log(`🚀 API请求详情:`);
        // console.log(`  方法: ${config.method?.toUpperCase()}`);
        // console.log(`  完整URL: ${config.baseURL}${config.url}`);
        // console.log(`  参数:`, config.params);
        // console.log(`  数据:`, config.data);
        // console.log(`  请求配置:`, config);

        return config;
    },
    (error: AxiosError) => {
        console.error('❌ 请求错误:', error);
        ElMessage.error('网络请求失败，请检查网络连接');
        return Promise.reject(error);
    }
);

// 响应拦截器
instance.interceptors.response.use(
    (response: AxiosResponse) => {
        const endTime = new Date();
        const startTime = (response.config as ExtendedAxiosRequestConfig).metadata?.startTime;
        const duration = startTime ? endTime.getTime() - startTime.getTime() : 0;

        console.log(`✅ API响应: ${response.config.method?.toUpperCase()} ${response.config.url} (${duration}ms)`, response.data);

        // 处理API响应结构
        if (response.data && typeof response.data === 'object') {
            // 如果响应有我们的标准ApiResponse结构
            if ('code' in response.data && 'success' in response.data) {
                const apiResponse = response.data as ApiResponse;

                // 检查业务状态码
                if (apiResponse.code !== 200 || !apiResponse.success) {
                    // 显示错误消息
                    ElMessage.error(apiResponse.msg || '请求失败');
                    return Promise.reject(new Error(apiResponse.msg || '请求失败'));
                }

                // 返回解构后的data数据
                return apiResponse.data;
            }

            // 如果是直接的数据响应，直接返回
            return response.data;
        }

        return response.data;
    },
    (error: AxiosError) => {
        const endTime = new Date();
        const startTime = (error.config as ExtendedAxiosRequestConfig)?.metadata?.startTime;
        const duration = startTime ? endTime.getTime() - startTime.getTime() : 0;

        console.error(`❌ API错误: ${error.config?.method?.toUpperCase()} ${error.config?.url} (${duration}ms)`, error);

        // 处理不同类型的错误
        if (error.response) {
            // 服务器响应了错误状态码
            const { status, data } = error.response;
            console.error(`服务器错误 ${status}:`, data);

            // 处理特定错误码
            let errorMessage = '请求失败';

            switch (status) {
                case 400:
                    errorMessage = '请求参数错误';
                    break;
                case 401:
                    errorMessage = '未授权访问，请重新登录';
                    // 可以在这里添加路由跳转到登录页
                    break;
                case 403:
                    errorMessage = '访问被拒绝';
                    break;
                case 404:
                    errorMessage = '请求的资源不存在';
                    break;
                case 500:
                    errorMessage = '服务器内部错误';
                    break;
                case 502:
                    errorMessage = '网关错误';
                    break;
                case 503:
                    errorMessage = '服务暂时不可用';
                    break;
                default:
                    errorMessage = `请求失败 (${status})`;
            }

            // 如果有服务器返回的错误消息，优先使用
            if (data && typeof data === 'object' && 'msg' in data) {
                errorMessage = String(data.msg);
            }

            ElMessage.error(errorMessage);
        } else if (error.request) {
            // 请求已发出但没有收到响应
            if (error.code === 'ECONNABORTED') {
                // 请求超时
                ElMessage.error('请求超时，请检查网络连接或稍后重试');
            } else if (error.code === 'ERR_NETWORK') {
                // 网络错误
                ElMessage.error('网络连接失败，请检查网络设置');
            } else if (error.code === 'ERR_CANCELED') {
                // 请求被取消
                console.log('请求已取消');
                // 不显示错误消息，因为这是用户主动取消
                return Promise.reject(error);
            } else {
                // 其他网络错误
                ElMessage.error('网络连接失败，请检查网络设置');
            }
        } else {
            // 其他错误（如请求配置错误）
            ElMessage.error(`请求设置错误: ${error.message}`);
        }

        return Promise.reject(error);
    }
);

// 便捷的HTTP方法封装
class HttpService {
    private instance = instance;

    /* GET 方法 */
    get<T = any>(url: string, params?: object, timeout?: number, requestId?: string): Promise<T> {
        const config: any = { params };
        if (timeout) config.timeout = timeout;
        if (requestId) {
            config.cancelToken = cancelTokenManager.createToken(requestId).token;
        }
        return this.instance.get(url, config).then(response => response as T).finally(() => {
            if (requestId) {
                cancelTokenManager.removeToken(requestId);
            }
        });
    }

    /* POST 方法 */
    post<T = any>(url: string, data?: object, timeout?: number, requestId?: string, config?: any): Promise<T> {
        const requestConfig: any = { ...config };
        if (timeout) requestConfig.timeout = timeout;
        if (requestId) {
            requestConfig.cancelToken = cancelTokenManager.createToken(requestId).token;
        }
        return this.instance.post(url, data, requestConfig).then(response => response as T).finally(() => {
            if (requestId) {
                cancelTokenManager.removeToken(requestId);
            }
        });
    }

    /* PUT 方法 */
    put<T = any>(url: string, data?: object, timeout?: number, requestId?: string, config?: any): Promise<T> {
        const requestConfig: any = { ...config };
        if (timeout) requestConfig.timeout = timeout;
        if (requestId) {
            requestConfig.cancelToken = cancelTokenManager.createToken(requestId).token;
        }
        return this.instance.put(url, data, requestConfig).then(response => response as T).finally(() => {
            if (requestId) {
                cancelTokenManager.removeToken(requestId);
            }
        });
    }

    /* DELETE 方法 */
    delete<T = any>(url: string, timeout?: number, requestId?: string, config?: any): Promise<T> {
        const requestConfig: any = { ...config };
        if (timeout) requestConfig.timeout = timeout;
        if (requestId) {
            requestConfig.cancelToken = cancelTokenManager.createToken(requestId).token;
        }
        return this.instance.delete(url, requestConfig).then(response => response as T).finally(() => {
            if (requestId) {
                cancelTokenManager.removeToken(requestId);
            }
        });
    }

    /* PATCH 方法 */
    patch<T = any>(url: string, data?: object, timeout?: number, requestId?: string, config?: any): Promise<T> {
        const requestConfig: any = { ...config };
        if (timeout) requestConfig.timeout = timeout;
        if (requestId) {
            requestConfig.cancelToken = cancelTokenManager.createToken(requestId).token;
        }
        return this.instance.patch(url, data, requestConfig).then(response => response as T).finally(() => {
            if (requestId) {
                cancelTokenManager.removeToken(requestId);
            }
        });
    }

    /* 设置默认超时时间 */
    setDefaultTimeout(timeout: number): void {
        this.instance.defaults.timeout = timeout;
    }

    /* 清除默认超时时间 */
    clearDefaultTimeout(): void {
        delete this.instance.defaults.timeout;
    }

    /* 取消特定请求 */
    cancelRequest(requestId: string): boolean {
        return cancelTokenManager.cancelRequest(requestId);
    }

    /* 取消所有请求 */
    cancelAllRequests(): void {
        cancelTokenManager.cancelAllRequests();
    }
}

// 创建HTTP服务实例
const httpService = new HttpService();

// 导出默认实例和HTTP服务
export default instance;
export { httpService, cancelTokenManager };

// 类型安全的API请求函数
export async function apiRequest<T = any>(
    config: InternalAxiosRequestConfig
): Promise<T> {
    try {
        const response = await instance(config);
        return response as T;
    } catch (error) {
        // 重新抛出错误，由调用代码处理
        throw error;
    }
} 